package com.firemoss.atonement.test.changewatcher.valuecomparison
{
	import com.firemoss.atonement.changewatcher.valuecomparison.*;
	
	import flash.utils.Dictionary;
	
	import mx.collections.ArrayCollection;
	import mx.collections.IList;
	
	import org.flexunit.asserts.*;

	public class TestDefaultEqualityComparitor
	{	
		private var comp:IValueComparitor = new DefaultComparitor();
			
		[Before]
		public function setUp():void
		{
		}
		
		[After]
		public function tearDown():void
		{
		}
		
		[BeforeClass]
		public static function setUpBeforeClass():void
		{
		}
		
		[AfterClass]
		public static function tearDownAfterClass():void
		{
		}
		
		[Test]
		public function strings_should_compare_by_value() : void
		{
			assertNull( comp.compare( "foo", "foo" ) );
			assertEquals( "bar", comp.compare( "foo", "bar" ) );
		}

		[Test]
		public function dates_should_compare_by_value() : void
		{
			var val1 : Date = new Date();
			var val2 : Date = new Date( val1.time );
			var val3 : Date = new Date( val1.time - 1 );
			assertNull( comp.compare( val1, val2 ) );
			assertEquals( val3, comp.compare( val1, val3 ) );
		}
		
		[Test]
		public function lists_should_compare_by_content_reference() : void
		{
			var obj1 : Object = {}
			var obj2 : Object = {}
			var obj3 : Object = {}
			
			var val1 : IList = new ArrayCollection( [ obj1, obj2 ] );
			var val2 : IList = new ArrayCollection( [ obj1, obj2 ] );
			var val3 : IList = new ArrayCollection( [ obj1 ] );
			var val4 : IList = new ArrayCollection( [ obj1, obj3 ] );
			
			assertNull( comp.compare( val1, val2 ) );
			assertEquals( val3, comp.compare( val1, val3 ) );
			assertEquals( val4, comp.compare( val1, val4 ) );
		}

		[Test]
		public function lists_should_compare_contained_complex_values_using_their_comparitor() : void
		{
			var obj1 : Object = {}
			var obj2 : Object = {}
			var obj3 : Object = {}
			
			var val1 : IList = new ArrayCollection( [ obj1, new ArrayCollection( [ obj2, obj3 ] ), makeDictionary( { 1 : obj1, 2 : obj2 } ) ] );
			var val2 : IList = new ArrayCollection( [ obj1, new ArrayCollection( [ obj2, obj3 ] ), makeDictionary( { 1 : obj1, 2 : obj2 } ) ] );
			var val3 : IList = new ArrayCollection( [ obj1, new ArrayCollection( [ obj3, obj2 ] ), makeDictionary( { 1 : obj1, 2 : obj2 } ) ] );
			var val4 : IList = new ArrayCollection( [ obj1, new ArrayCollection( [ obj2, obj3 ] ), makeDictionary( { 1 : obj1, 2 : obj3 } ) ] );
			
			assertNull( comp.compare( val1, val2 ) );
			assertEquals( val3, comp.compare( val1, val3 ) );
			assertEquals( val4, comp.compare( val1, val4 ) );
		}

		[Test]
		public function dicts_should_compare_by_content_reference() : void
		{
			var obj1 : Object = {}
			var obj2 : Object = {}
			var obj3 : Object = {}
			
			var val1 : Dictionary = makeDictionary( { "key1" : obj1, "key2" : obj2 } );
			var val2 : Dictionary = makeDictionary( { "key1" : obj1, "key2" : obj2 } );
			var val3 : Dictionary = makeDictionary( { "key1" : obj1 } );
			var val4 : Dictionary = makeDictionary( { "key1" : obj1, "key2" : obj3 } );
			var val5 : Dictionary = makeDictionary( { "key1" : obj1, "key3" : obj2 } );
			var val6 : Dictionary = makeDictionary( { "key1" : obj1, "key2" : obj2, "key3" : obj3 } );
			
			assertNull( comp.compare( val1, val2 ) );
			assertEquals( val3, comp.compare( val1, val3 ) );
			assertEquals( val4, comp.compare( val1, val4 ) );
			assertEquals( val5, comp.compare( val1, val5 ) );
			assertEquals( val6, comp.compare( val1, val6 ) );
		}

		[Test]
		public function dicts_should_compare_contained_complex_values_using_their_comparitor() : void
		{
			var obj1 : Object = {}
			var obj2 : Object = {}
			var obj3 : Object = {}
			
			var val1 : Dictionary = makeDictionary( { 1 : obj1, 2 : new ArrayCollection( [ obj2, obj3 ] ), 3 : makeDictionary( { 1 : obj1, 2 : obj2 } ) } );
			var val2 : Dictionary = makeDictionary( { 1 : obj1, 2 : new ArrayCollection( [ obj2, obj3 ] ), 3 : makeDictionary( { 1 : obj1, 2 : obj2 } ) } );
			var val3 : Dictionary = makeDictionary( { 1 : obj1, 2 : new ArrayCollection( [ obj2, obj1 ] ), 3 : makeDictionary( { 1 : obj1, 2 : obj2 } ) } );
			var val4 : Dictionary = makeDictionary( { 1 : obj1, 2 : new ArrayCollection( [ obj2, obj3 ] ), 3 : makeDictionary( { 1 : obj1, 2 : obj3 } ) } );
			
			assertNull( comp.compare( val1, val2 ) );
			assertEquals( val3, comp.compare( val1, val3 ) );
			assertEquals( val4, comp.compare( val1, val4 ) );
		}
		
		private function makeDictionary( src : Object ) : Dictionary
		{
			var dict : Dictionary = new Dictionary()
				
			for ( var key:* in src )
			{
				dict[key] = src[key]
			}
			
			return dict
		}
	}
}